package com.pine.dbant.common.plugin.impl;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.pine.dbant.common.model.TableSource;
import com.pine.dbant.common.plugin.SqlSchemaStatVisitor;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiaoyuan
 * @create 2023/3/17 14:19
 **/
public class DefaultSqlSchemaStatVisitor extends MySqlSchemaStatVisitor implements SqlSchemaStatVisitor {
    @Override
    public List<TableSource> getColumnsOfTableSources(String sql) {
        // 使用Parser解析生成AST，这里SQLStatement就是AST
        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.mysql);
        stmt.accept(this);
        return getColumns().stream().map(column -> {
            List<String> table = parserTableName(column.getTable());
            if (table.size() == 2) {
                return TableSource.builder().catalog(table.get(0)).tableName(table.get(1)).fullName(column.getTable()).build();
            }
            return TableSource.builder().tableName(column.getTable()).fullName(column.getTable()).build();
        }).collect(Collectors.toList());
    }


    private List<String> parserTableName(String name) {
        char quoteChar = '`';
        char splitChar = '.';
        List<Character> arr = new ArrayList<>();
        boolean quoteCharFlag = false;
        char c;
        char[] nameC = name.toCharArray();
        List<String> result = new ArrayList<>();
        for (int i = 0; i < nameC.length; i++) {
            c = nameC[i];
            if (c == quoteChar) {
                if (quoteCharFlag) {
                    quoteCharFlag = false;
                } else {
                    quoteCharFlag = true;
                }
                continue;
            }
            if (c == splitChar && !quoteCharFlag) {
                result.add(toString(arr));
                arr.clear();
                continue;
            }
            arr.add(c);
        }
        if (!arr.isEmpty()) {
            result.add(toString(arr));
        }
        if (result.isEmpty()) {
            result.add(name);
        }
        return result;
    }


    private String toString(List<Character> arr ){
        StringBuffer stringBuffer  = new StringBuffer();
        for(Character c:arr){
            stringBuffer.append(c);
        }
        return stringBuffer.toString();
    }


}
